{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-11-03T08:33:13.498201Z",
     "start_time": "2019-11-03T08:33:12.355186Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "    <div class=\"bk-root\">\n",
       "        <a href=\"https://bokeh.pydata.org\" target=\"_blank\" class=\"bk-logo bk-logo-small bk-logo-notebook\"></a>\n",
       "        <span id=\"1001\">Loading BokehJS ...</span>\n",
       "    </div>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/javascript": [
       "\n",
       "(function(root) {\n",
       "  function now() {\n",
       "    return new Date();\n",
       "  }\n",
       "\n",
       "  var force = true;\n",
       "\n",
       "  if (typeof (root._bokeh_onload_callbacks) === \"undefined\" || force === true) {\n",
       "    root._bokeh_onload_callbacks = [];\n",
       "    root._bokeh_is_loading = undefined;\n",
       "  }\n",
       "\n",
       "  var JS_MIME_TYPE = 'application/javascript';\n",
       "  var HTML_MIME_TYPE = 'text/html';\n",
       "  var EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json';\n",
       "  var CLASS_NAME = 'output_bokeh rendered_html';\n",
       "\n",
       "  /**\n",
       "   * Render data to the DOM node\n",
       "   */\n",
       "  function render(props, node) {\n",
       "    var script = document.createElement(\"script\");\n",
       "    node.appendChild(script);\n",
       "  }\n",
       "\n",
       "  /**\n",
       "   * Handle when an output is cleared or removed\n",
       "   */\n",
       "  function handleClearOutput(event, handle) {\n",
       "    var cell = handle.cell;\n",
       "\n",
       "    var id = cell.output_area._bokeh_element_id;\n",
       "    var server_id = cell.output_area._bokeh_server_id;\n",
       "    // Clean up Bokeh references\n",
       "    if (id != null && id in Bokeh.index) {\n",
       "      Bokeh.index[id].model.document.clear();\n",
       "      delete Bokeh.index[id];\n",
       "    }\n",
       "\n",
       "    if (server_id !== undefined) {\n",
       "      // Clean up Bokeh references\n",
       "      var cmd = \"from bokeh.io.state import curstate; print(curstate().uuid_to_server['\" + server_id + \"'].get_sessions()[0].document.roots[0]._id)\";\n",
       "      cell.notebook.kernel.execute(cmd, {\n",
       "        iopub: {\n",
       "          output: function(msg) {\n",
       "            var id = msg.content.text.trim();\n",
       "            if (id in Bokeh.index) {\n",
       "              Bokeh.index[id].model.document.clear();\n",
       "              delete Bokeh.index[id];\n",
       "            }\n",
       "          }\n",
       "        }\n",
       "      });\n",
       "      // Destroy server and session\n",
       "      var cmd = \"import bokeh.io.notebook as ion; ion.destroy_server('\" + server_id + \"')\";\n",
       "      cell.notebook.kernel.execute(cmd);\n",
       "    }\n",
       "  }\n",
       "\n",
       "  /**\n",
       "   * Handle when a new output is added\n",
       "   */\n",
       "  function handleAddOutput(event, handle) {\n",
       "    var output_area = handle.output_area;\n",
       "    var output = handle.output;\n",
       "\n",
       "    // limit handleAddOutput to display_data with EXEC_MIME_TYPE content only\n",
       "    if ((output.output_type != \"display_data\") || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n",
       "      return\n",
       "    }\n",
       "\n",
       "    var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n",
       "\n",
       "    if (output.metadata[EXEC_MIME_TYPE][\"id\"] !== undefined) {\n",
       "      toinsert[toinsert.length - 1].firstChild.textContent = output.data[JS_MIME_TYPE];\n",
       "      // store reference to embed id on output_area\n",
       "      output_area._bokeh_element_id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n",
       "    }\n",
       "    if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n",
       "      var bk_div = document.createElement(\"div\");\n",
       "      bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n",
       "      var script_attrs = bk_div.children[0].attributes;\n",
       "      for (var i = 0; i < script_attrs.length; i++) {\n",
       "        toinsert[toinsert.length - 1].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value);\n",
       "      }\n",
       "      // store reference to server id on output_area\n",
       "      output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n",
       "    }\n",
       "  }\n",
       "\n",
       "  function register_renderer(events, OutputArea) {\n",
       "\n",
       "    function append_mime(data, metadata, element) {\n",
       "      // create a DOM node to render to\n",
       "      var toinsert = this.create_output_subarea(\n",
       "        metadata,\n",
       "        CLASS_NAME,\n",
       "        EXEC_MIME_TYPE\n",
       "      );\n",
       "      this.keyboard_manager.register_events(toinsert);\n",
       "      // Render to node\n",
       "      var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n",
       "      render(props, toinsert[toinsert.length - 1]);\n",
       "      element.append(toinsert);\n",
       "      return toinsert\n",
       "    }\n",
       "\n",
       "    /* Handle when an output is cleared or removed */\n",
       "    events.on('clear_output.CodeCell', handleClearOutput);\n",
       "    events.on('delete.Cell', handleClearOutput);\n",
       "\n",
       "    /* Handle when a new output is added */\n",
       "    events.on('output_added.OutputArea', handleAddOutput);\n",
       "\n",
       "    /**\n",
       "     * Register the mime type and append_mime function with output_area\n",
       "     */\n",
       "    OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n",
       "      /* Is output safe? */\n",
       "      safe: true,\n",
       "      /* Index of renderer in `output_area.display_order` */\n",
       "      index: 0\n",
       "    });\n",
       "  }\n",
       "\n",
       "  // register the mime type if in Jupyter Notebook environment and previously unregistered\n",
       "  if (root.Jupyter !== undefined) {\n",
       "    var events = require('base/js/events');\n",
       "    var OutputArea = require('notebook/js/outputarea').OutputArea;\n",
       "\n",
       "    if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n",
       "      register_renderer(events, OutputArea);\n",
       "    }\n",
       "  }\n",
       "\n",
       "  \n",
       "  if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n",
       "    root._bokeh_timeout = Date.now() + 5000;\n",
       "    root._bokeh_failed_load = false;\n",
       "  }\n",
       "\n",
       "  var NB_LOAD_WARNING = {'data': {'text/html':\n",
       "     \"<div style='background-color: #fdd'>\\n\"+\n",
       "     \"<p>\\n\"+\n",
       "     \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n",
       "     \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n",
       "     \"</p>\\n\"+\n",
       "     \"<ul>\\n\"+\n",
       "     \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n",
       "     \"<li>use INLINE resources instead, as so:</li>\\n\"+\n",
       "     \"</ul>\\n\"+\n",
       "     \"<code>\\n\"+\n",
       "     \"from bokeh.resources import INLINE\\n\"+\n",
       "     \"output_notebook(resources=INLINE)\\n\"+\n",
       "     \"</code>\\n\"+\n",
       "     \"</div>\"}};\n",
       "\n",
       "  function display_loaded() {\n",
       "    var el = document.getElementById(\"1001\");\n",
       "    if (el != null) {\n",
       "      el.textContent = \"BokehJS is loading...\";\n",
       "    }\n",
       "    if (root.Bokeh !== undefined) {\n",
       "      if (el != null) {\n",
       "        el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n",
       "      }\n",
       "    } else if (Date.now() < root._bokeh_timeout) {\n",
       "      setTimeout(display_loaded, 100)\n",
       "    }\n",
       "  }\n",
       "\n",
       "\n",
       "  function run_callbacks() {\n",
       "    try {\n",
       "      root._bokeh_onload_callbacks.forEach(function(callback) { callback() });\n",
       "    }\n",
       "    finally {\n",
       "      delete root._bokeh_onload_callbacks\n",
       "    }\n",
       "    console.info(\"Bokeh: all callbacks have finished\");\n",
       "  }\n",
       "\n",
       "  function load_libs(js_urls, callback) {\n",
       "    root._bokeh_onload_callbacks.push(callback);\n",
       "    if (root._bokeh_is_loading > 0) {\n",
       "      console.log(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n",
       "      return null;\n",
       "    }\n",
       "    if (js_urls == null || js_urls.length === 0) {\n",
       "      run_callbacks();\n",
       "      return null;\n",
       "    }\n",
       "    console.log(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n",
       "    root._bokeh_is_loading = js_urls.length;\n",
       "    for (var i = 0; i < js_urls.length; i++) {\n",
       "      var url = js_urls[i];\n",
       "      var s = document.createElement('script');\n",
       "      s.src = url;\n",
       "      s.async = false;\n",
       "      s.onreadystatechange = s.onload = function() {\n",
       "        root._bokeh_is_loading--;\n",
       "        if (root._bokeh_is_loading === 0) {\n",
       "          console.log(\"Bokeh: all BokehJS libraries loaded\");\n",
       "          run_callbacks()\n",
       "        }\n",
       "      };\n",
       "      s.onerror = function() {\n",
       "        console.warn(\"failed to load library \" + url);\n",
       "      };\n",
       "      console.log(\"Bokeh: injecting script tag for BokehJS library: \", url);\n",
       "      document.getElementsByTagName(\"head\")[0].appendChild(s);\n",
       "    }\n",
       "  };var element = document.getElementById(\"1001\");\n",
       "  if (element == null) {\n",
       "    console.log(\"Bokeh: ERROR: autoload.js configured with elementid '1001' but no matching script tag was found. \")\n",
       "    return false;\n",
       "  }\n",
       "\n",
       "  var js_urls = [\"https://cdn.pydata.org/bokeh/release/bokeh-1.0.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.0.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-tables-1.0.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-gl-1.0.0.min.js\"];\n",
       "\n",
       "  var inline_js = [\n",
       "    function(Bokeh) {\n",
       "      Bokeh.set_log_level(\"info\");\n",
       "    },\n",
       "    \n",
       "    function(Bokeh) {\n",
       "      \n",
       "    },\n",
       "    function(Bokeh) {\n",
       "      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-1.0.0.min.css\");\n",
       "      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-1.0.0.min.css\");\n",
       "      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.0.0.min.css\");\n",
       "      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.0.0.min.css\");\n",
       "      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-tables-1.0.0.min.css\");\n",
       "      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-tables-1.0.0.min.css\");\n",
       "    }\n",
       "  ];\n",
       "\n",
       "  function run_inline_js() {\n",
       "    \n",
       "    if ((root.Bokeh !== undefined) || (force === true)) {\n",
       "      for (var i = 0; i < inline_js.length; i++) {\n",
       "        inline_js[i].call(root, root.Bokeh);\n",
       "      }if (force === true) {\n",
       "        display_loaded();\n",
       "      }} else if (Date.now() < root._bokeh_timeout) {\n",
       "      setTimeout(run_inline_js, 100);\n",
       "    } else if (!root._bokeh_failed_load) {\n",
       "      console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n",
       "      root._bokeh_failed_load = true;\n",
       "    } else if (force !== true) {\n",
       "      var cell = $(document.getElementById(\"1001\")).parents('.cell').data().cell;\n",
       "      cell.output_area.append_execute_result(NB_LOAD_WARNING)\n",
       "    }\n",
       "\n",
       "  }\n",
       "\n",
       "  if (root._bokeh_is_loading === 0) {\n",
       "    console.log(\"Bokeh: BokehJS loaded, going straight to plotting\");\n",
       "    run_inline_js();\n",
       "  } else {\n",
       "    load_libs(js_urls, function() {\n",
       "      console.log(\"Bokeh: BokehJS plotting callback run at\", now());\n",
       "      run_inline_js();\n",
       "    });\n",
       "  }\n",
       "}(window));"
      ],
      "application/vnd.bokehjs_load.v0+json": "\n(function(root) {\n  function now() {\n    return new Date();\n  }\n\n  var force = true;\n\n  if (typeof (root._bokeh_onload_callbacks) === \"undefined\" || force === true) {\n    root._bokeh_onload_callbacks = [];\n    root._bokeh_is_loading = undefined;\n  }\n\n  \n\n  \n  if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n    root._bokeh_timeout = Date.now() + 5000;\n    root._bokeh_failed_load = false;\n  }\n\n  var NB_LOAD_WARNING = {'data': {'text/html':\n     \"<div style='background-color: #fdd'>\\n\"+\n     \"<p>\\n\"+\n     \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n     \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n     \"</p>\\n\"+\n     \"<ul>\\n\"+\n     \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n     \"<li>use INLINE resources instead, as so:</li>\\n\"+\n     \"</ul>\\n\"+\n     \"<code>\\n\"+\n     \"from bokeh.resources import INLINE\\n\"+\n     \"output_notebook(resources=INLINE)\\n\"+\n     \"</code>\\n\"+\n     \"</div>\"}};\n\n  function display_loaded() {\n    var el = document.getElementById(\"1001\");\n    if (el != null) {\n      el.textContent = \"BokehJS is loading...\";\n    }\n    if (root.Bokeh !== undefined) {\n      if (el != null) {\n        el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n      }\n    } else if (Date.now() < root._bokeh_timeout) {\n      setTimeout(display_loaded, 100)\n    }\n  }\n\n\n  function run_callbacks() {\n    try {\n      root._bokeh_onload_callbacks.forEach(function(callback) { callback() });\n    }\n    finally {\n      delete root._bokeh_onload_callbacks\n    }\n    console.info(\"Bokeh: all callbacks have finished\");\n  }\n\n  function load_libs(js_urls, callback) {\n    root._bokeh_onload_callbacks.push(callback);\n    if (root._bokeh_is_loading > 0) {\n      console.log(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n      return null;\n    }\n    if (js_urls == null || js_urls.length === 0) {\n      run_callbacks();\n      return null;\n    }\n    console.log(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n    root._bokeh_is_loading = js_urls.length;\n    for (var i = 0; i < js_urls.length; i++) {\n      var url = js_urls[i];\n      var s = document.createElement('script');\n      s.src = url;\n      s.async = false;\n      s.onreadystatechange = s.onload = function() {\n        root._bokeh_is_loading--;\n        if (root._bokeh_is_loading === 0) {\n          console.log(\"Bokeh: all BokehJS libraries loaded\");\n          run_callbacks()\n        }\n      };\n      s.onerror = function() {\n        console.warn(\"failed to load library \" + url);\n      };\n      console.log(\"Bokeh: injecting script tag for BokehJS library: \", url);\n      document.getElementsByTagName(\"head\")[0].appendChild(s);\n    }\n  };var element = document.getElementById(\"1001\");\n  if (element == null) {\n    console.log(\"Bokeh: ERROR: autoload.js configured with elementid '1001' but no matching script tag was found. \")\n    return false;\n  }\n\n  var js_urls = [\"https://cdn.pydata.org/bokeh/release/bokeh-1.0.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.0.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-tables-1.0.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-gl-1.0.0.min.js\"];\n\n  var inline_js = [\n    function(Bokeh) {\n      Bokeh.set_log_level(\"info\");\n    },\n    \n    function(Bokeh) {\n      \n    },\n    function(Bokeh) {\n      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-1.0.0.min.css\");\n      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-1.0.0.min.css\");\n      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.0.0.min.css\");\n      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.0.0.min.css\");\n      console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/release/bokeh-tables-1.0.0.min.css\");\n      Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/release/bokeh-tables-1.0.0.min.css\");\n    }\n  ];\n\n  function run_inline_js() {\n    \n    if ((root.Bokeh !== undefined) || (force === true)) {\n      for (var i = 0; i < inline_js.length; i++) {\n        inline_js[i].call(root, root.Bokeh);\n      }if (force === true) {\n        display_loaded();\n      }} else if (Date.now() < root._bokeh_timeout) {\n      setTimeout(run_inline_js, 100);\n    } else if (!root._bokeh_failed_load) {\n      console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n      root._bokeh_failed_load = true;\n    } else if (force !== true) {\n      var cell = $(document.getElementById(\"1001\")).parents('.cell').data().cell;\n      cell.output_area.append_execute_result(NB_LOAD_WARNING)\n    }\n\n  }\n\n  if (root._bokeh_is_loading === 0) {\n    console.log(\"Bokeh: BokehJS loaded, going straight to plotting\");\n    run_inline_js();\n  } else {\n    load_libs(js_urls, function() {\n      console.log(\"Bokeh: BokehJS plotting callback run at\", now());\n      run_inline_js();\n    });\n  }\n}(window));"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import torchvision.datasets as dsets\n",
    "import torchvision.transforms as transforms\n",
    "from torch.utils.data import DataLoader\n",
    "\n",
    "from bokeh.io import show, output_notebook\n",
    "from bokeh.plotting import figure, gridplot\n",
    "from bokeh.models import LinearAxis, Range1d\n",
    "output_notebook()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-11-02T15:34:18.036850Z",
     "start_time": "2019-11-02T15:34:18.032937Z"
    }
   },
   "source": [
    "### Data\n",
    "通过`torchvision.datasets`下载`MNIST`数据。  \n",
    "训练集：`train=True`  \n",
    "测试集：`train=False`  \n",
    "常用的还有`torchvision.datasets.ImageFolder()`，按文件夹取图片。  \n",
    "\n",
    "`torchvision.transforms`可以对图片做处理。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-11-03T08:33:13.531748Z",
     "start_time": "2019-11-03T08:33:13.499689Z"
    }
   },
   "outputs": [],
   "source": [
    "train_dataset = dsets.MNIST(root='../dataset', train=True, transform=transforms.ToTensor(), download=True)\n",
    "test_dataset = dsets.MNIST(root='../dataset', train=False, transform=transforms.ToTensor(), download=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-11-03T08:33:13.642186Z",
     "start_time": "2019-11-03T08:33:13.533425Z"
    }
   },
   "outputs": [],
   "source": [
    "batch_size = 50\n",
    "train_loader = DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)\n",
    "test_loader = DataLoader(dataset=test_dataset, batch_size=1, shuffle=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Model\n",
    "构造前馈神经网络"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-11-03T08:33:13.742569Z",
     "start_time": "2019-11-03T08:33:13.644037Z"
    }
   },
   "outputs": [],
   "source": [
    "class FNN(nn.Module):\n",
    "    def __init__(self, dim_in, dim_hidden, dim_out):\n",
    "        super().__init__()\n",
    "        self.fc1 = nn.Linear(dim_in, dim_hidden)\n",
    "        self.relu = nn.ReLU()\n",
    "        self.fc2 = nn.Linear(dim_hidden, dim_out)\n",
    "    def forward(self, x):\n",
    "        return self.fc2(self.relu(self.fc1(x)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-11-03T08:33:13.881193Z",
     "start_time": "2019-11-03T08:33:13.744548Z"
    }
   },
   "outputs": [],
   "source": [
    "dim_in = 28*28\n",
    "dim_hidden = 500\n",
    "dim_out = 10\n",
    "lrate = 0.001\n",
    "epochs = 20\n",
    "\n",
    "model = FNN(dim_in, dim_hidden, dim_out).double()\n",
    "criterion = nn.CrossEntropyLoss()\n",
    "optim = torch.optim.SGD(model.parameters(), lr=lrate)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "注意：每次反向传播的时候都需要将参数的梯度归零。  \n",
    "`optim.step()`则在每个`Variable`的`grad`都被计算出来后，更新每个`Variable`的数值"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在每次训练中都用`train_loader`中的一个`batch`作为训练数据。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-11-03T08:41:47.035889Z",
     "start_time": "2019-11-03T08:33:13.886494Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "\n",
       "\n",
       "\n",
       "\n",
       "\n",
       "  <div class=\"bk-root\" id=\"25822b72-5f97-40ae-b448-2f10113845a6\"></div>\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/javascript": [
       "(function(root) {\n",
       "  function embed_document(root) {\n",
       "    \n",
       "  var docs_json = {\"1711c0f8-49d3-45d4-b699-c4a835c4cc75\":{\"roots\":{\"references\":[{\"attributes\":{\"below\":[{\"id\":\"1011\",\"type\":\"LinearAxis\"}],\"left\":[{\"id\":\"1016\",\"type\":\"LinearAxis\"}],\"renderers\":[{\"id\":\"1011\",\"type\":\"LinearAxis\"},{\"id\":\"1015\",\"type\":\"Grid\"},{\"id\":\"1016\",\"type\":\"LinearAxis\"},{\"id\":\"1020\",\"type\":\"Grid\"},{\"id\":\"1029\",\"type\":\"BoxAnnotation\"},{\"id\":\"1039\",\"type\":\"GlyphRenderer\"}],\"title\":{\"id\":\"1042\",\"type\":\"Title\"},\"toolbar\":{\"id\":\"1027\",\"type\":\"Toolbar\"},\"x_range\":{\"id\":\"1003\",\"type\":\"DataRange1d\"},\"x_scale\":{\"id\":\"1007\",\"type\":\"LinearScale\"},\"y_range\":{\"id\":\"1005\",\"type\":\"DataRange1d\"},\"y_scale\":{\"id\":\"1009\",\"type\":\"LinearScale\"}},\"id\":\"1002\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"active_drag\":\"auto\",\"active_inspect\":\"auto\",\"active_multi\":null,\"active_scroll\":\"auto\",\"active_tap\":\"auto\",\"tools\":[{\"id\":\"1021\",\"type\":\"PanTool\"},{\"id\":\"1022\",\"type\":\"WheelZoomTool\"},{\"id\":\"1023\",\"type\":\"BoxZoomTool\"},{\"id\":\"1024\",\"type\":\"SaveTool\"},{\"id\":\"1025\",\"type\":\"ResetTool\"},{\"id\":\"1026\",\"type\":\"HelpTool\"}]},\"id\":\"1027\",\"type\":\"Toolbar\"},{\"attributes\":{},\"id\":\"1007\",\"type\":\"LinearScale\"},{\"attributes\":{\"bottom_units\":\"screen\",\"fill_alpha\":{\"value\":0.5},\"fill_color\":{\"value\":\"lightgrey\"},\"left_units\":\"screen\",\"level\":\"overlay\",\"line_alpha\":{\"value\":1.0},\"line_color\":{\"value\":\"black\"},\"line_dash\":[4,4],\"line_width\":{\"value\":2},\"plot\":null,\"render_mode\":\"css\",\"right_units\":\"screen\",\"top_units\":\"screen\"},\"id\":\"1029\",\"type\":\"BoxAnnotation\"},{\"attributes\":{\"callback\":null},\"id\":\"1005\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"1009\",\"type\":\"LinearScale\"},{\"attributes\":{\"source\":{\"id\":\"1036\",\"type\":\"ColumnDataSource\"}},\"id\":\"1040\",\"type\":\"CDSView\"},{\"attributes\":{\"formatter\":{\"id\":\"1045\",\"type\":\"BasicTickFormatter\"},\"plot\":{\"id\":\"1002\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"1012\",\"type\":\"BasicTicker\"}},\"id\":\"1011\",\"type\":\"LinearAxis\"},{\"attributes\":{\"plot\":null,\"text\":\"\"},\"id\":\"1042\",\"type\":\"Title\"},{\"attributes\":{},\"id\":\"1012\",\"type\":\"BasicTicker\"},{\"attributes\":{\"callback\":null,\"data\":{\"x\":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19],\"y\":[1.9962015689068326,1.5931185530607794,1.1361166400280838,0.9313625277348706,0.7541278068529909,0.8026120473647694,0.7813324225275065,0.5471593038845366,0.682574884040771,0.7188732699734011,0.3693293986696038,0.4570680018967307,0.525436411804142,0.4689172768152145,0.41423754454799794,0.3653722707709418,0.6218445734249515,0.570350951016001,0.6630052394108542,0.3854849405204903]},\"selected\":{\"id\":\"1048\",\"type\":\"Selection\"},\"selection_policy\":{\"id\":\"1049\",\"type\":\"UnionRenderers\"}},\"id\":\"1036\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"plot\":{\"id\":\"1002\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"1012\",\"type\":\"BasicTicker\"}},\"id\":\"1015\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"1048\",\"type\":\"Selection\"},{\"attributes\":{\"formatter\":{\"id\":\"1043\",\"type\":\"BasicTickFormatter\"},\"plot\":{\"id\":\"1002\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"1017\",\"type\":\"BasicTicker\"}},\"id\":\"1016\",\"type\":\"LinearAxis\"},{\"attributes\":{\"callback\":null},\"id\":\"1003\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"1049\",\"type\":\"UnionRenderers\"},{\"attributes\":{},\"id\":\"1017\",\"type\":\"BasicTicker\"},{\"attributes\":{},\"id\":\"1045\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"dimension\":1,\"plot\":{\"id\":\"1002\",\"subtype\":\"Figure\",\"type\":\"Plot\"},\"ticker\":{\"id\":\"1017\",\"type\":\"BasicTicker\"}},\"id\":\"1020\",\"type\":\"Grid\"},{\"attributes\":{\"data_source\":{\"id\":\"1036\",\"type\":\"ColumnDataSource\"},\"glyph\":{\"id\":\"1037\",\"type\":\"Line\"},\"hover_glyph\":null,\"muted_glyph\":null,\"nonselection_glyph\":{\"id\":\"1038\",\"type\":\"Line\"},\"selection_glyph\":null,\"view\":{\"id\":\"1040\",\"type\":\"CDSView\"}},\"id\":\"1039\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"line_color\":\"#1f77b4\",\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1037\",\"type\":\"Line\"},{\"attributes\":{\"line_alpha\":0.1,\"line_color\":\"#1f77b4\",\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1038\",\"type\":\"Line\"},{\"attributes\":{},\"id\":\"1021\",\"type\":\"PanTool\"},{\"attributes\":{},\"id\":\"1022\",\"type\":\"WheelZoomTool\"},{\"attributes\":{\"overlay\":{\"id\":\"1029\",\"type\":\"BoxAnnotation\"}},\"id\":\"1023\",\"type\":\"BoxZoomTool\"},{\"attributes\":{},\"id\":\"1024\",\"type\":\"SaveTool\"},{\"attributes\":{},\"id\":\"1043\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{},\"id\":\"1025\",\"type\":\"ResetTool\"},{\"attributes\":{},\"id\":\"1026\",\"type\":\"HelpTool\"}],\"root_ids\":[\"1002\"]},\"title\":\"Bokeh Application\",\"version\":\"1.0.0\"}};\n",
       "  var render_items = [{\"docid\":\"1711c0f8-49d3-45d4-b699-c4a835c4cc75\",\"roots\":{\"1002\":\"25822b72-5f97-40ae-b448-2f10113845a6\"}}];\n",
       "  root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n",
       "\n",
       "  }\n",
       "  if (root.Bokeh !== undefined) {\n",
       "    embed_document(root);\n",
       "  } else {\n",
       "    var attempts = 0;\n",
       "    var timer = setInterval(function(root) {\n",
       "      if (root.Bokeh !== undefined) {\n",
       "        embed_document(root);\n",
       "        clearInterval(timer);\n",
       "      }\n",
       "      attempts++;\n",
       "      if (attempts > 100) {\n",
       "        console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n",
       "        clearInterval(timer);\n",
       "      }\n",
       "    }, 10, root)\n",
       "  }\n",
       "})(window);"
      ],
      "application/vnd.bokehjs_exec.v0+json": ""
     },
     "metadata": {
      "application/vnd.bokehjs_exec.v0+json": {
       "id": "1002"
      }
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "result = []\n",
    "for e in range(epochs):\n",
    "    for i, (inputs, targets) in enumerate(train_loader):\n",
    "        inputs = inputs.reshape(-1, 28*28).double()\n",
    "        optim.zero_grad()\n",
    "        outputs = model(inputs)\n",
    "        loss = criterion(outputs, targets)\n",
    "        loss.backward()\n",
    "        optim.step()\n",
    "    result.append(float(loss))\n",
    "    \n",
    "fig = figure()\n",
    "fig.line(range(len(result)), result)\n",
    "show(fig)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Result\n",
    "检验预测结果"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`re = torch.max(Tensor,dim)`, 返回的re为一个二维向量，其中`re[0]`为最大值的`Tensor`，re[1]为最大值对应的`index`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-11-03T08:41:58.152705Z",
     "start_time": "2019-11-03T08:41:47.040995Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy of the model on the 10000 test images: 90.20 %\n"
     ]
    }
   ],
   "source": [
    "correct = 0\n",
    "total = 0\n",
    "wrong_count = 0\n",
    "wrong_classify = []\n",
    "for i, (inputs, targets) in enumerate(test_loader):\n",
    "    inputs = inputs.reshape(-1, 28*28).double()\n",
    "    outputs = model(inputs)\n",
    "    _, preds = torch.max(outputs.data, 1)\n",
    "    total += len(outputs)\n",
    "    correct += (preds == targets).sum()\n",
    "    if wrong_count < 5 and preds != targets:\n",
    "        wrong_classify.append([inputs.data, preds, targets])\n",
    "        wrong_count += 1\n",
    "accuracy = 100 * correct.double() / total\n",
    "print('Accuracy of the model on the 10000 test images: %.2f %%' % (accuracy))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-11-03T08:41:59.086596Z",
     "start_time": "2019-11-03T08:41:58.157171Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1080x5400 with 5 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=(15, wrong_count*15))\n",
    "for i, (img, preds, truth) in enumerate(wrong_classify):\n",
    "    img = img.reshape(28, 28).numpy()\n",
    "    plt.subplot(1, wrong_count, i+1)\n",
    "    plt.imshow(img)\n",
    "    plt.title('true:%i, pred:%i' % (truth, preds))\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-11-03T07:12:44.915877Z",
     "start_time": "2019-11-03T07:12:44.913744Z"
    }
   },
   "source": [
    "### Save Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-11-03T08:41:59.144452Z",
     "start_time": "2019-11-03T08:41:59.088635Z"
    }
   },
   "outputs": [],
   "source": [
    "torch.save(model.state_dict(), 'feedfoward_nn.pkl')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.1"
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "oldHeight": 511.99678000000006,
   "position": {
    "height": "533.984px",
    "left": "411.875px",
    "right": "20px",
    "top": "161.984px",
    "width": "760.516px"
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "varInspector_section_display": "block",
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
